# baseline twfe models
rm(list = ls())
library(data.table)
library(dplyr)
library(plm)
library(lmtest)
library(sandwich)
library(stargazer)
options(dplyr.summarise.inform = FALSE)
# load data
df <- fread("data/monarch_panel_transformed.csv")
if (!dir.exists("tables")) {
dir.create("tables")
}
# clustered se
cluster_se <- function(model) {
sqrt(diag(vcovHC(model, type = "HC1", cluster = "group")))
}
# function
run_twfe_incremental <- function(depvar, fd, fd_x_ipr, outfile, title) {
# maximize samples by finance type
base <- df %>%
filter(
!is.na(.data[[depvar]]),
!is.na(.data[[fd]]),
!is.na(ipr_c)
)
panel <- pdata.frame(base, index = c("iso3c", "year"))
# specifications
f1 <- as.formula(paste(depvar, "~", fd, "+ ipr_c +", fd_x_ipr))
f2 <- update(f1, . ~ . + ln_gdp_pc)
f3 <- update(f2, . ~ . + ln_trade)
f4 <- update(f3, . ~ . + ln_rd)
f5 <- update(f4, . ~ . + ln_tertiary)
m1 <- plm(f1, data = panel, model = "within", effect = "twoways")
m2 <- plm(f2, data = panel, model = "within", effect = "twoways")
m3 <- plm(f3, data = panel, model = "within", effect = "twoways")
m4 <- plm(f4, data = panel, model = "within", effect = "twoways")
m5 <- plm(f5, data = panel, model = "within", effect = "twoways")
html_table <- capture.output(
stargazer(
m1, m2, m3, m4, m5,
type = "html",
title = title,
dep.var.caption = ifelse(
depvar == "quality_index_100",
"Dependent Variable: Patent Quality (0–100)",
"Dependent Variable: ln(Patents per 1,000 Researchers)"
),
se = list(
cluster_se(m1),
cluster_se(m2),
cluster_se(m3),
cluster_se(m4),
cluster_se(m5)
),
omit.stat = c("ser", "f"),
notes = c(
"Country and year fixed effects included in all models.",
"Standard errors clustered by country.",
"* p<0.1; ** p<0.05; *** p<0.01"
),
no.space = TRUE
)
)
cat(paste(html_table, collapse = "\n"))
# latex tables
stargazer(
m1, m2, m3, m4, m5,
type = "latex",
out = outfile,
title = title,
dep.var.caption = ifelse(
depvar == "quality_index_100",
"Dependent Variable: Patent Quality (0–100)",
"Dependent Variable: ln(Patents per 1,000 Researchers)"
),
se = list(
cluster_se(m1),
cluster_se(m2),
cluster_se(m3),
cluster_se(m4),
cluster_se(m5)
),
omit.stat = c("ser", "f"),
notes = c(
"Country and year fixed effects included in all models.",
"Standard errors clustered by country.",
"* p<0.1; ** p<0.05; *** p<0.01"
),
no.space = TRUE
)
return(list(m1, m2, m3, m4, m5))
}
# quality models
market_quality <- run_twfe_incremental(
depvar = "quality_index_100",
fd = "ln_market",
fd_x_ipr = "ln_market_x_ipr",
outfile = "tables/twfe_market_quality.tex",
title = "Market Finance and Patent Quality"
)